﻿/**
 * @file main.c
 * Copyright (c) 2024 Gaaagaa. All rights reserved.
 * 
 * @author  : Gaaagaa
 * @date    : 2024-08-08
 * @version : 1.0.0.0
 * @brief   : 测试 bitset 。
 */

#include "std_bitset.h"
#include "std_bitset.inl"

#include <stdio.h>
#include <stdlib.h>

////////////////////////////////////////////////////////////////////////////////

#define _S_LINE(x)  #x
#define __S_LINE(x) _S_LINE(x)
#define __S_LINE__  __S_LINE(__LINE__)

#define X_VLEN_256  256

////////////////////////////////////////////////////////////////////////////////

/**********************************************************/
/**
 * @brief 显示 位集合对象 内容。
 */
void bitset_show(xbs_this_t xbs_this, const char * xsz_title)
{
    xstd_size_t xst_ipos = 0;

    printf("\n========================================\n");
    printf(
        "Title  : %s\n"
        "Size   : %d\n"
        "Marked : %d\n",
        xsz_title,
        (xstd_int32_t)std_bitset_size(xbs_this),
        (xstd_int32_t)std_bitset_count(xbs_this));

    for (; xst_ipos < XBS_IPOS_END(xbs_this); )
    {
        printf("%d", XBS_ISMARK(xbs_this, xst_ipos));

        ++xst_ipos;
        if (0 == (xst_ipos % 32))
            printf("\n");
        else if (0 == (xst_ipos % 4))
            printf(" ");
    }

    if (0 != (xst_ipos % 32))
    {
        printf("\n");
    }

    printf("========================================\n");
}

/**********************************************************/
/**
 * @brief 填充 位集合对象 内容。
 */
void bitset_fill(xbs_this_t xbs_this, const xstd_byte_t xbs_bits[16])
{
    xbs_ipos_t xbs_ipos = 0;

    std_bitset_reset(xbs_this);

    for (; xbs_ipos < (16 * 8); ++xbs_ipos)
    {
        if (xbs_bits[xbs_ipos >> 3] & (((xstd_byte_t)1) << (xbs_ipos & 0x07)))
            std_bitset_marki(xbs_this, (xbs_ipos_t)xbs_ipos, XBS_MARKED);
        else
            std_bitset_marki(xbs_this, (xbs_ipos_t)xbs_ipos, XBS_UNMARKED);
    }
}

/**********************************************************/
/**
 * @brief 测试 bitset_testi() 接口。
 */
void testi(xbs_this_t xbs_this)
{
    xbs_ipos_t xbs_ipos;

    xstd_byte_t xbs_bits0[16] =
    {
        0b00000001, 0b00000000, 0b00000000, 0b10101010,
        0b00000000, 0b00000000, 0b10101010, 0b00000000,
        0b00000000, 0b00000000, 0b00000000, 0b10101010,
        0b10000000, 0b00000000, 0b00000000, 0b10101010
    };

    //======================================

    bitset_fill(xbs_this, xbs_bits0);
    bitset_show(xbs_this, __func__);

    //======================================

    printf("bitset marks:\n");
    for (xbs_ipos = XBS_IBEGIN; xbs_ipos < XBS_IPOS_END(xbs_this); )
    {
        printf("[%3d, %d]", (xstd_int32_t)xbs_ipos, std_bitset_testi(xbs_this, xbs_ipos, XBS_MARKED));

        ++xbs_ipos;
        if (0 == (xbs_ipos % 16))
            printf("\n");
        else
            printf(" ");
    }

    if (0 != (xbs_ipos % 16))
    {
        printf("\n");
    }

    //======================================

    printf("bitset unmarks:\n");
    for (xbs_ipos = XBS_IBEGIN; xbs_ipos < XBS_IPOS_END(xbs_this); )
    {
        printf("[%3d, %d]", (xstd_int32_t)xbs_ipos, std_bitset_testi(xbs_this, xbs_ipos, XBS_UNMARKED));

        ++xbs_ipos;
        if (0 == (xbs_ipos % 16))
            printf("\n");
        else
            printf(" ");
    }

    if (0 != (xbs_ipos % 16))
    {
        printf("\n");
    }

    //======================================
}

/**********************************************************/
/**
 * @brief 测试 bitset_testn() 接口。
 */
void testn(xbs_this_t xbs_this)
{
    xbs_ipos_t xbs_ibgn;
    xbs_ipos_t xbs_iend;

    xstd_byte_t xbs_bits0[16] =
    {
        0b00000001, 0b00000000, 0b00000000, 0b00101010,
        0b00000000, 0b00000000, 0b00000000, 0b00000000,
        0b00000000, 0b00000000, 0b00000000, 0b00000000,
        0b00000000, 0b00000000, 0b00000100, 0b10101010
    };

    //======================================

    bitset_fill(xbs_this, xbs_bits0);
    bitset_show(xbs_this, __func__);

    //======================================

#define TEST_CASE(begin, end)                                                            \
    do                                                                                   \
    {                                                                                    \
        xbs_ibgn = (begin);                                                              \
        xbs_iend = (end);                                                                \
        printf("testn [ %3d, %3d )   marked : %d\n",                                     \
            (xstd_int32_t)xbs_ibgn, (xstd_int32_t)xbs_iend,                              \
            (xstd_int32_t)std_bitset_testn(xbs_this, xbs_ibgn, xbs_iend, XBS_MARKED));   \
        printf("testn [ %3d, %3d ) unmarked : %d\n",                                     \
            (xstd_int32_t)xbs_ibgn, (xstd_int32_t)xbs_iend,                              \
            (xstd_int32_t)std_bitset_testn(xbs_this, xbs_ibgn, xbs_iend, XBS_UNMARKED)); \
    } while (0)

    //======================================

    TEST_CASE(  0, 128);
    TEST_CASE(  1,   6);
    TEST_CASE(  1,  24);
    TEST_CASE( 30, 128);
    TEST_CASE( 37, 128);

    //======================================
#undef TEST_CASE
    //======================================
}

/**********************************************************/
/**
 * @brief 测试 bitset_markn() 接口。
 */
void markn(xbs_this_t xbs_this)
{
    xbs_ipos_t xbs_ibgn;
    xbs_ipos_t xbs_iend;

    xstd_byte_t xbs_bits0[16] =
    {
        0b00000000, 0b00000000, 0b00000000, 0b00101010,
        0b00000000, 0b00000000, 0b00000000, 0b00000000,
        0b00000000, 0b00000000, 0b00000000, 0b00000000,
        0b00000000, 0b00000000, 0b00000100, 0b10101010
    };

    xstd_byte_t xbs_bits1[16] =
    {
        0b00000000, 0b00000000, 0b00000000, 0b10101010,
        0b11111111, 0b11111111, 0b11111111, 0b11111111,
        0b11111111, 0b11111111, 0b11111111, 0b11111111,
        0b00000111, 0b00000000, 0b00000100, 0b10101010
    };

    xstd_char_t xsz_title[X_VLEN_256];

    //======================================

    snprintf(xsz_title, X_VLEN_256, "%s bits0", __func__);
    bitset_fill(xbs_this, xbs_bits0);
    bitset_show(xbs_this, xsz_title);

    snprintf(xsz_title, X_VLEN_256, "%s bits1", __func__);
    bitset_fill(xbs_this, xbs_bits1);
    bitset_show(xbs_this, xsz_title);

    //======================================

#define TEST_CASE(begin, end, bits)                                               \
    do                                                                            \
    {                                                                             \
        xbs_ibgn = (begin);                                                       \
        xbs_iend = (end);                                                         \
                                                                                  \
        bitset_fill(xbs_this, (bits));                                            \
        snprintf(xsz_title, X_VLEN_256, "[%d] markn [ %3d, %3d ) marked : %d",    \
                 __LINE__, (xstd_int32_t)xbs_ibgn, (xstd_int32_t)xbs_iend,        \
                 std_bitset_markn(xbs_this, xbs_ibgn, xbs_iend, XBS_MARKED));     \
        bitset_show(xbs_this, xsz_title);                                         \
                                                                                  \
        bitset_fill(xbs_this, (bits));                                            \
        snprintf(xsz_title, X_VLEN_256, "[%d] markn [ %3d, %3d ) unmarked : %d",  \
                __LINE__, (xstd_int32_t)xbs_ibgn, (xstd_int32_t)xbs_iend,         \
                std_bitset_markn(xbs_this, xbs_ibgn, xbs_iend, XBS_UNMARKED));    \
        bitset_show(xbs_this, xsz_title);                                         \
    } while (0)

    //======================================

    TEST_CASE( 0, 128, xbs_bits0);
    TEST_CASE( 3,  28, xbs_bits0);
    TEST_CASE( 3,  24, xbs_bits0);
    TEST_CASE(30, 100, xbs_bits0);
    TEST_CASE(30, 122, xbs_bits0);
    TEST_CASE(30,  98, xbs_bits1);
    TEST_CASE(31,  98, xbs_bits1);

    //======================================
#undef TEST_CASE
    //======================================
}

/**********************************************************/
/**
 * @brief 测试 btiset_flipn() 接口。
 */
void flipn(xbs_this_t xbs_this)
{
    xbs_ipos_t xbs_ibgn;
    xbs_ipos_t xbs_iend;

    xstd_byte_t xbs_bits0[16] =
    {
        0b00000000, 0b00000000, 0b00000000, 0b00101010,
        0b00000000, 0b00000000, 0b00000000, 0b00000000,
        0b00000000, 0b00000000, 0b00000000, 0b00000000,
        0b00000000, 0b00000000, 0b00000100, 0b10101010
    };

    xstd_byte_t xbs_bits1[16] =
    {
        0b00000000, 0b00000000, 0b00000000, 0b10101010,
        0b11111111, 0b11111111, 0b11111111, 0b11111111,
        0b11111111, 0b11111111, 0b11111111, 0b11111111,
        0b00000111, 0b00000000, 0b00000100, 0b10101010
    };

    xstd_char_t xsz_title[X_VLEN_256];

    //======================================

    snprintf(xsz_title, X_VLEN_256, "%s bits0", __func__);
    bitset_fill(xbs_this, xbs_bits0);
    bitset_show(xbs_this, xsz_title);

    snprintf(xsz_title, X_VLEN_256, "%s bits1", __func__);
    bitset_fill(xbs_this, xbs_bits1);
    bitset_show(xbs_this, xsz_title);

    //======================================

    bitset_fill(xbs_this, xbs_bits0);
    for (xbs_ibgn = 0; xbs_ibgn < 128; ++xbs_ibgn)
    {
        std_bitset_flipi(xbs_this, xbs_ibgn);
    }
    bitset_show(xbs_this, "flipi bits0");

    bitset_fill(xbs_this, xbs_bits1);
    for (xbs_ibgn = 0; xbs_ibgn < 128; ++xbs_ibgn)
    {
        std_bitset_flipi(xbs_this, xbs_ibgn);
    }
    bitset_show(xbs_this, "flipi bits1");

    //======================================

#define TEST_CASE(begin, end, bits)                                \
    do                                                             \
    {                                                              \
        xbs_ibgn = (begin);                                        \
        xbs_iend = (end);                                          \
        bitset_fill(xbs_this, (bits));                             \
        snprintf(xsz_title, X_VLEN_256, "before flipn [ %d, %d )", \
                 (xstd_int32_t)xbs_ibgn, (xstd_int32_t)xbs_iend);  \
        bitset_show(xbs_this, xsz_title);                          \
        std_bitset_flipn(xbs_this, xbs_ibgn, xbs_iend);            \
        snprintf(xsz_title, X_VLEN_256, "after  flipn [ %d, %d )", \
                 (xstd_int32_t)xbs_ibgn, (xstd_int32_t)xbs_iend);  \
        bitset_show(xbs_this, xsz_title);                          \
    } while (0);

    //======================================

    TEST_CASE(0, 128, xbs_bits0);
    TEST_CASE(0, 128, xbs_bits1);

    TEST_CASE(30, 120, xbs_bits0);
    TEST_CASE(30, 120, xbs_bits1);

    //======================================
#undef TEST_CASE
    //======================================
}

/**********************************************************/
/**
 * @brief 测试 bitset_findi() 接口。
 */
void findi(xbs_this_t xbs_this)
{
    xbs_ipos_t xbs_ipos;

    xstd_byte_t xbs_bits0[16] =
    {
        0b00000000, 0b00000000, 0b00000000, 0b00101010,
        0b00000000, 0b00000000, 0b00000000, 0b00000000,
        0b00000000, 0b00000000, 0b00000000, 0b00000000,
        0b00000000, 0b00000000, 0b00000100, 0b10101010
    };

    xstd_byte_t xbs_bits1[16] =
    {
        0b00000000, 0b00000000, 0b00000000, 0b10101010,
        0b11111111, 0b11111111, 0b11111111, 0b11111111,
        0b11111111, 0b11111111, 0b11111111, 0b11111111,
        0b00000111, 0b00000000, 0b00000100, 0b10101010
    };

    xstd_char_t xsz_title[X_VLEN_256];

    //======================================

    snprintf(xsz_title, X_VLEN_256, "%s bits0", __func__);
    bitset_fill(xbs_this, xbs_bits0);
    bitset_show(xbs_this, xsz_title);

    snprintf(xsz_title, X_VLEN_256, "%s bits1", __func__);
    bitset_fill(xbs_this, xbs_bits1);
    bitset_show(xbs_this, xsz_title);

    //======================================

#define TEST_CASE(begin, bits)                                                 \
    do                                                                         \
    {                                                                          \
        xbs_ipos = (begin);                                                    \
        bitset_fill(xbs_this, (bits));                                         \
        printf("%s findi[%3d] first   marked pos: %d\n",                       \
            #bits, (xstd_int32_t)xbs_ipos,                                     \
            (xstd_int32_t)std_bitset_findi(xbs_this, xbs_ipos, XBS_MARKED));   \
        printf("%s findi[%3d] first unmarked pos: %d\n",                       \
            #bits, (xstd_int32_t)xbs_ipos,                                     \
            (xstd_int32_t)std_bitset_findi(xbs_this, xbs_ipos, XBS_UNMARKED)); \
    } while (0)

    //======================================

    TEST_CASE(  0, xbs_bits0);
    TEST_CASE( 11, xbs_bits0);
    TEST_CASE(128, xbs_bits0);
    TEST_CASE( 32, xbs_bits1);
    TEST_CASE( 70, xbs_bits1);
    TEST_CASE(128, xbs_bits1);

    //======================================
#undef TEST_CASE
    //======================================
}

/**********************************************************/
/**
 * @brief 测试 bitset_findn() 接口。
 */
void findn(xbs_this_t xbs_this)
{
    xbs_ipos_t xbs_ipos;
    xbs_size_t xst_nbit;

    xstd_byte_t xbs_bits0[16] =
    {
        0b00000000, 0b00000000, 0b00000000, 0b00101010,
        0b00000000, 0b00000000, 0b00000000, 0b00000000,
        0b00000000, 0b00000000, 0b00000000, 0b00000000,
        0b00000000, 0b00000000, 0b00000100, 0b10101010
    };

    xstd_byte_t xbs_bits1[16] =
    {
        0b00000000, 0b00000000, 0b00000000, 0b10101010,
        0b11111111, 0b11111111, 0b11111111, 0b11111111,
        0b11111111, 0b11111111, 0b11111111, 0b11111111,
        0b00000111, 0b00000000, 0b00000100, 0b10101010
    };

    xstd_char_t xsz_title[X_VLEN_256];

    //======================================

    snprintf(xsz_title, X_VLEN_256, "%s bits0", __func__);
    bitset_fill(xbs_this, xbs_bits0);
    bitset_show(xbs_this, xsz_title);

    snprintf(xsz_title, X_VLEN_256, "%s bits1", __func__);
    bitset_fill(xbs_this, xbs_bits1);
    bitset_show(xbs_this, xsz_title);

    //======================================

#define TEST_CASE(ipos, nbit, bits)                                                         \
    do                                                                                      \
    {                                                                                       \
        xbs_ipos = (ipos);                                                                  \
        xst_nbit = (nbit);                                                                  \
        bitset_fill(xbs_this, (bits));                                                      \
        printf("%s findn[%3d, %3d]   marked pos: %d\n",                                     \
               #bits, (xstd_int32_t)xbs_ipos, (xstd_int32_t)xst_nbit,                       \
               (xstd_int32_t)std_bitset_findn(xbs_this, xbs_ipos, xst_nbit, XBS_MARKED));   \
        printf("%s findn[%3d, %3d] unmarked pos: %d\n",                                     \
               #bits, (xstd_int32_t)xbs_ipos, (xstd_int32_t)xst_nbit,                       \
               (xstd_int32_t)std_bitset_findn(xbs_this, xbs_ipos, xst_nbit, XBS_UNMARKED)); \
    } while (0)

    //======================================

    TEST_CASE(  0,   7, xbs_bits0);
    TEST_CASE(  0,  25, xbs_bits0);
    TEST_CASE(  0, 125, xbs_bits0);
    TEST_CASE( 21,   7, xbs_bits0);
    TEST_CASE( 32,  25, xbs_bits0);
    TEST_CASE(100, 125, xbs_bits0);

    TEST_CASE(  0,   7, xbs_bits1);
    TEST_CASE(  0,  25, xbs_bits1);
    TEST_CASE(  0, 125, xbs_bits1);
    TEST_CASE( 21,   7, xbs_bits1);
    TEST_CASE( 32,  25, xbs_bits1);
    TEST_CASE(100, 125, xbs_bits1);

    //======================================
#undef TEST_CASE
    //======================================
}

////////////////////////////////////////////////////////////////////////////////

/**********************************************************/
/**
 * @brief main function.
 */
int main(int argc, char * argv[])
{
    xstd_bitset_t xbs_this;
    std_bitset_emplace_create(&xbs_this, XBS_NULL, 128);

    //======================================

#if 1
    testi(&xbs_this);
    testn(&xbs_this);
    markn(&xbs_this);
    flipn(&xbs_this);
    findi(&xbs_this);
#endif
    findn(&xbs_this);

    //======================================

    std_bitset_emplace_destroy(&xbs_this);

    return 0;
}

////////////////////////////////////////////////////////////////////////////////
